/**
 * 
 */
package hu.cubussapiens.client.core.query;

import hu.cubussapiens.client.core.login.AppManager;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactoryConfigurationError;

import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PutMethod;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
 * @author balage
 *
 */
public abstract class AbstractQueryGenerator {

	public List<String> execute(AppManager manager) throws QueryExecutionException{
	
		DocumentBuilder builder;
		try {
			builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			throw new QueryExecutionException(e);
		}
		final Document doc = builder.newDocument();
		Element query = doc.createElement("query");
		doc.appendChild(query);
		this.doc = doc;
		
		query.appendChild(generateQuery());
		
		PutMethod put = new PutMethod(manager.getApproot()+"cms");
		try {
			put.setRequestEntity(new XMLRequestEntity(doc));
		} catch (TransformerFactoryConfigurationError e) {
			throw new QueryExecutionException(e);
		} catch (TransformerException e) {
			throw new QueryExecutionException(e);
		} catch (IOException e) {
			throw new QueryExecutionException(e);
		}
		
		try {
			manager.execute(put);
		} catch (HttpException e) {
			throw new QueryExecutionException(e);
		} catch (IOException e) {
			throw new QueryExecutionException(e);
		}
		
		List<String> result = new ArrayList<String>();
		try {
			BufferedReader bf = new BufferedReader(new InputStreamReader(put.getResponseBodyAsStream()));
			String line = null;
			while((line = bf.readLine())!=null){
				line = line.trim();
				if (!"".equals(line))
					result.add(line);
			}
		} catch (IOException e) {
			throw new QueryExecutionException(e);
		}
		return result;
	}
	
	private Document doc;
	
	protected abstract Element generateQuery();
	
	protected final Element literal(String data){
		Element literal = doc.createElement("literal");
		literal.setAttribute("data", data);
		return literal;
	}
	
	protected final Element createLiteral(String data){
		return createLiteral(data,-1l);
	}
	
	protected final Element createLiteral(String data, Long accessticket){
		Element createliteral = doc.createElement("createliteral");
		createliteral.setAttribute("data", data);
		createliteral.setAttribute("access", accessticket.toString());
		return createliteral;
	}
	
	protected final Element construct(Element object, Element verb, Element subject){
		Element construct = doc.createElement("construct");
		construct.appendChild(object);
		construct.appendChild(verb);
		construct.appendChild(subject);
		return construct;
	}
	
	protected final Element selectObject(Element verb, Element subject){
		Element select = doc.createElement("selectObject");
		select.appendChild(verb);
		select.appendChild(subject);
		return select;
	}
	
	protected final Element selectVerb(Element object, Element subject){
		Element select = doc.createElement("selectVerb");
		select.appendChild(object);
		select.appendChild(subject);
		return select;
	}
	
	protected final Element selectSubject(Element object, Element verb){
		Element select = doc.createElement("selectSubject");
		select.appendChild(object);
		select.appendChild(verb);
		return select;
	}
	
	protected final Element and(Element...queries){
		Element and = doc.createElement("and");
		for(Element e : queries)
			and.appendChild(e);
		return and;
	}
	
	protected final Element or(Element...queries){
		Element and = doc.createElement("or");
		for(Element e : queries)
			and.appendChild(e);
		return and;
	}
	
}
